import time

import pywintypes
import win32file
import win32pipe
from PyQt5.QtCore import QThread, pyqtSignal

PIPE_NAME = r'\\.\pipe\MyInvoicePrinter'


class PipeManager(QThread):
    message_received = pyqtSignal(str)
    finished = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.pipe_name = PIPE_NAME
        self.pipe = None
        self._isRunning = False

    def run(self):
        self._isRunning = True
        self.finished.connect(self.deleteLater)
        if not self.pipe:
            self.create()
        while self._isRunning:
            try:
                win32pipe.ConnectNamedPipe(self.pipe)

                while True:
                    time.sleep(0.1)
                    (err, data) = win32file.ReadFile(self.pipe, 65536)
                    message = data.decode('utf-8')
                    if message:
                        self.message_received.emit(message)
            except pywintypes.error as e:
                if e.winerror == 109:
                    self.close()
                    self.create()
                    continue
                # print(e)

        self.finished.emit()

    def stop(self):
        self._isRunning = False

    def create(self):
        self.pipe = win32pipe.CreateNamedPipe(
            self.pipe_name,
            win32pipe.PIPE_ACCESS_DUPLEX,
            win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
            1,  # max instances
            65536,  # output buffer size
            65536,  # input buffer size
            300,  # timeout
            None  # security attributes
        )

    def close(self):
        if self.pipe:
            win32file.CloseHandle(self.pipe)
            self.pipe = None

    @staticmethod
    def already_exists():
        try:
            pipe = win32file.CreateFile(
                PIPE_NAME,
                win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                0,
                None,
                win32file.OPEN_EXISTING,
                0,
                None
            )
            win32file.WriteFile(pipe, "Activate".encode('utf-8'))
            win32file.FlushFileBuffers(pipe)
            win32file.CloseHandle(pipe)
            return True
        except pywintypes.error as e:
            if e.winerror == 2:  # Error code 2 means "The system cannot find the file specified."
                return False
            raise
